Technote 1192ATA Interface Modules |
CONTENTSIntroductionCore Concepts ATA Manager Additions AIM Packaging AIM Entry Points AIM Action Function Codes AIM Support Routines |
This Technote describes how to write a device driver for an ATA host bus controller, known as an ATA Interface Module, or AIM. An AIM is the ATA equivalent of the SCSI Interface Module (SIM). It does not control a device on the ATA bus, but implements a standard hardware abstraction for the bus itself. AIMs operate at the very lowest level of the traditional Mac OS I/O subsystem, which makes them hard to write and hard to debug. Only experienced Mac OS device driver writers should consider developing an AIM. This Note is directed at developers of ATA host bus controller cards (typically PCI or CardBus). |
IntroductionThis technote describes how to write a Mac OS device driver for ATA host bus controller hardware. Such a driver is known as an ATA Interface Module, or AIM. In some respects it is the ATA equivalent to the more commonly known SCSI Interface Module (SIM). This technote is divided into two sections. This section, and the Core Concepts sections which follows it, represent the introductory material. They describe high-level issues with writing AIMs; understanding these sections is critical to writing a reliable AIM. The remaining sections are reference material. They describe how you can register an ATA bus with ATA Manager, how you should package your AIM so that it is recognized by ATA Manager, what entry points ATA Manager expects you AIM to implement, the list of function codes your AIM's action routine must support, and some support routines that ATA Manager exports to support AIM implementation.
Before You BeginBefore you consider developing an AIM, you should be familiar with the following concepts:
You will also need the following:
|
Core ConceptsBefore starting your AIM, you should be familiar with some fundamental concepts, as described in the following sections. Theory of OperationAIMs represent an abstraction of an ATA bus. Your AIM isolates the ATA Manager and its clients from the specific details of your ATA bus controller hardware. For instance, an ATA bus may be part of a PC Card slot, or perhaps reside on a PCI card, or may even be integrated as part of a system chipset. Each physical ATA controller will have specific requirements for how it is addressed, what cycle times are supported and how they are programmed, how interrupts from the controller are routed to the system, and so on. By bundling the hardware-specific details of the ATA controller in a plug-in software module, the ATA Manager presents a consistent interface for drivers and applications to communicate with ATA and ATAPI devices. All of the operations which directly touch the hardware in any manner are handled by your AIM. This includes:
Current versions of ATA Manager will only dispatch a single request for a single device on the bus controlled by your AIM at any given time. Overlapped ATA/ATAPI features are not currently supported. AIMs written to the specification in this document will never be expected to handle concurrent requests. In general, your AIM should be interrupt-driven. It
should do as much work as it can on a request, then return
to the ATA Manager pending an interrupt from the hardware.
For instance, when you receive a request to read data, you
would set your AIM's internal flags as needed, write the
task file to the device, and then return to ATA Manager.
When the device is ready to transfer data, it will assert an
interrupt which will call your AIM's hardware interrupt
handler. Your AIM would then call
There are some limits on the controller hardware that can be supported by an AIM:
Global VariablesYour AIM should allocate its per-bus global variables in
a memory block (typically allocated use
The reason to use the
Regardless of how you allocate your global variables, you must ensure that they are held resident in memory (in the virtual memory sense). All of the techniques described above guarantee this. Finally, your AIM should use PowerPC structure alignment for its global variables. This has two advantages:
AIM Update ProcessAs mentioned above, the ATA Manager has a process for updating your AIM to a newer version "on the fly," without shutting the bus down. The ATA Manager accomplishes this in a 7 step process:
There are a number of important things about this process to keep in mind.
AIM Synchronization ModelAs long as you follow one simple rule, the ATA Manager takes care of most of the synchronization problems in writing an AIM. The rule is:
Posting a bus event
( If you follow this rule, ATA Manager guarantees that it will never call your AIM on more than one thread of execution at a time. So as long as you're executing within the context of a routine that is called by ATA Manager, you can access global variables without worrying about synchronization issues. An obvious example of where this is useful is for
handling interrupts. As a rule, your AIM will service I/O
requests as a state machine. When ATA Manager calls your AIM
to start a request
(
A less obvious example of the use of bus events is to
handle timeouts. If your AIM implements timeouts using the
system timer service (
In addition to guaranteeing that only one thread of
execution can be running inside your AIM at any point in
time, the ATA Manager also guarantees to dispatch only a
single request to your AIM at a time. Between the point when
ATA Manager dispatches a request (by calling
Both of the synchronization guarantees described in this section are defined on a bus-by-bus basis. If your AIM is multiply instantiated on the system, and those instances share common data, you must be careful to synchronize access to that common data. Finally, ATA Manager also handles enabling and disabling
of user code (in the virtual memory sense) for you. Readers
who are familiar with SIMs (the equivalent to AIMs for SCSI
buses) know that they are required to call
ATA I/O ModesThis section explains one of the trickier aspects of the ATA Manager's API for setting transfer modes and timings. In addition to the discussion here, you should read the ATA Device Software for Macintosh Computers (and its errata, DTS Technote 1098 ATA Device Software Guide Additions and Corrections) carefully to fully understand how ATA client software expects your AIM to handle transfer modes and timings. Prior to ATA Manager 3.0, which was the first version of
the ATA Manager to support DMA transfers, transfer modes
were specified as absolute numbers. Thus, a value of 2 for a
transfer mode meant PIO mode 2. Starting with ATA Manager
3.0, transfer modes were specified as bitmaps. Thus a value
of 1 meant transfer mode 0, a value of 2 meant transfer mode
1, and so on. The This is important to remember when trying to establish
the correct timing mode on the ATA bus. For example, the
flag bit AIMs versus SIMsIn many respects, AIMs are architecturally similar to SCSI Interface Modules (SIMs), the name given to host bus controller drivers in the Mas OS SCSI architecture. The following table compares various features of AIMs and SIMs.
|
ATA Manager AdditionsATA Manager 4.0 defines two new ATA Manager function
codes to be used with the
Adding an ATA BusTo add an ATA bus to ATA Manager, you must call the
The fields have the following meaning:
In response to this request, the ATA Manager opens your
AIM and creates the internal data structures necessary for
it to track the AIM and its attached devices. As part of
processing this call, the ATA Manager calls your AIM's
initialization routine
( The possible flags for the
The meaning of these flags is:
You must issue this request at system task time. Removing an ATA BusTo remove an ATA bus, you must call the
The fields have the following meaning:
In response to this request the ATA Manager will remove
the ATA bus associated with the Name Registry node specified
in
You may issue this request at any execution level, although if you issue it at anything other than system task level the ATA Manager's connection to the AIM is not closed until a future system task time. |
AIM PackagingAn AIM is packaged as a native driver
Your AIM must export two named entry global variables:
The structure of these global variables is described in the following sections. TheDriverDescriptionAn AIM must export the standard native driver description structure under the name "TheDriverDescription". An example of how your AIM should fill out this structure is given below.
Some parts of this definition deserve further explanation.
ThePluginDispatchTableIn addition to the standard drive description, you AIM
must export a plugin dispatch table under the name
"ThePluginDispatchTable". The
The fields have the following meaning:
The
The fields have the following meaning:
|
AIM Entry PointsYour AIM must implement a number of routines and export those routines to the ATA Manager via the plugin dispatch table. This section describes these routines in detail. MyAIMInit
The ATA Manager calls your AIM's initialization routine to commence operations on the ATA bus controlled by your AIM. This routine is called when an ATA bus is registered with ATA Manager. Your AIM must allocate any private resources it needs (typically per-bus storage), install its interrupt handler, initialize its hardware, probe the bus for attached devices (and determine whether they are ATA or ATAPI), and return information about those devices to the ATA Manager. Depending on your hardware, your AIM may need to reset the ATA bus to determine if any devices are attached. Your AIM must also create child Name Registry nodes for the attached ATA devices. The nodes must have at least the following properties:
Your AIM initialization routine must not issue any commands to the ATA device. Your AIM's initialization routine receives the address of
an
The fields have the following meaning:
The
The fields have the following meaning:
If your AIM wants to indicate that no ATA device is
attach, it must set devType to
If your AIM initialization routine returns an error, or it indicates that there are no devices on the bus, ATA Manager fails the request to register the ATA bus, unloads your AIM, and dispose of all references to it.
Suggested result codes include:
This routine is always be called at system task time. MyAIMClose
The ATA Manager calls your AIM's close routine to terminate operations on the ATA bus controlled by your AIM. This routine is called when an ATA bus is deregistered with ATA Manager. Your AIM must shut down its hardware, remove any interrupt handlers, and release any resources it owns. This will be the last request that a particular instance of your AIM will receive. Any error code returned by your AIM is ignored. You should structure your AIM such that its close routine can not fail. This routine will always be called at system task time. MyAIMAction
The ATA Manager calls your AIM's action routine to
perform a transaction on the ATA bus. The
Unless otherwise stated, a field is has the same meaning
for all function codes (except
Each field is described in more detail with the appropriate function code. Your AIM typically processes an action request using a
state machine. When it receives the action request, it
initializes the state machine and starts the first
(asynchronous) step of processing the request. It then
returns control to the ATA Manager. When the first step is
complete, the hardware generates an interrupt and the AIM's
interrupt service routine is called. It notifies ATA Manager
of the bus event by calling
This routine may be called at any execution level. MyAIMHandleBusEvent
The ATA Manager calls your AIM's bus event handler routine to handle events detected on your bus. Typically these events are interrupts from your bus's interrupt hardware. Your AIM informs ATA Manager of these events in one of two ways:
Regardless of how it informs ATA Manager of the bus
event, your AIM can provide a bus event type which indicates
what type of bus event occurred. The ATA Manager passes the
same bus event type back to the bus event handler in the
Typically your AIM responds to a bus event by moving the
current I/O request to the next state. For example, if the
current I/O request is waiting for an I/O completion bus
event, your AIM would respond to that bus event by calling
This routine may be called at any execution level. It is typically executed with interrupts enabled (either from a deferred task or a secondary interrupt) but that is not guaranteed. MyAIMPoll
The ATA Manager calls your AIM's interrupt poll routine
when it detects that a synchronous I/O request is blocked
because interrupts are masked (or otherwise deferred). Your
AIM must look at its interrupt hardware to determine if
there is an interrupt pending. If there is, your AIM must
set the memory pointed to by The This routine may be called at any execution level. Background MaterialUnder the Mac OS I/O system architecture, it is possible for the system to take a page fault in three hard-to-handle cases:
Page faults result in synchronous disk driver I/O requests. If the underlying I/O hardware requires interrupts to complete an I/O request, and interrupts are masked or otherwise deferred when the page fault happens, the system will deadlock. In order to avoid this deadlock, the system polls for interrupts during any "sync wait" loop which occurs while interrupts are masked (or otherwise deferred). Given that the system has no knowledge of your AIM's interrupt architecture, it calls your AIM's interrupt poll routine to accomplish this polling. See DTS Technote 1094 Virtual Memory Application Compatibility and DTS Q&A DV 34 Secondary Interrupts on the Page Fault Path for more details about this technique. MyAIMEjectDevice
The ATA Manager calls your AIM's eject routine in
response to a
If your ejection hardware is asynchronous, this operation
should simply start the ejection operation. If an
asynchronous ejection operation is not complete by the time
the ATA bus is deregistered, your close routine
( This routine is optional. If your AIM does not support
this function, it should set the appropriate plugin dispatch
table entry to This routine may be called at any execution level. MyAIMDeviceLight
The ATA Manager calls your AIM's device light routine to
turn on and off the activity light, if any, associated with
your AIM. Typically the ATA Manager enables the activity
light in response to a device driver request (the driver
sets the The constants for the
An example of an AIM that implements this routine is the media bay AIM for PowerBook computers, where it controls the LED on the media bay device. This routine is optional. If your AIM does not support
this function, it should set the appropriate plugin dispatch
table entry to This routine may be called at any execution level. MyAIMDeviceLock
The ATA Manager calls your AIM's device lock routine to
lock and unlock the hardware associated with your AIM. A
locked device cannot be ejected by the user. The ATA Manager
locks and unlocks the AIM based on the
The constants for the
An example of an AIM that implements this routine is the built-in PC Card AIM, which prevents users from ejecting the PC Card if it has been locked. This routine is optional. If your AIM does not support
this function, it should set the appropriate plugin dispatch
table entry to This routine may be called at any execution level. MyAIMSuspend
The ATA Manager calls your AIM's suspend routine as part of the process of updating an AIM to a newer version. See AIM Update Process for more details. Your AIM must "disconnect" itself from all system callbacks except those directly associated with the ATA Manager. This includes:
This allows the ATA Manager to unload the code associated
with the older version of your AIM. Your AIM must not
dispose of the per-bus storage associated with
The ATA Manager guarantees that it will not call your AIM from the beginning of your suspend routine until your resume routine returns. This routine will always be called at system task time. MyAIMResume
The ATA Manager calls your AIM's resume routine as part of the process of updating an AIM to a newer version. See AIM Update Process for more details. Your AIM must "redisconnect" itself to all system callbacks which were disconnected by the suspend routine. This includes:
Your AIM is required to continue operations using the
per-bus storage inherited from the older version and pointed
to by The ATA Manager guarantees that it will not call your AIM from the beginning of your suspend routine until your resume routine returns. This routine will always be called at system task time. |
AIM Action Function CodesWhen ATA Manager calls your AIM's action routine
(
The following sections describe each function code in
detail. If your AIM receives a request with a function code
it does not recognize, it should fail the request with a
status of No Operation (kATAFnNOP)This is a "no operation" request. ATA Manager should
never issue this request to your AIM. If it does, your AIM
should immediately complete the request successfully by
calling
Execute I/O (kATAFnExecIO)ATA Manager issues this request to your AIM as the result
of a client's The structure of the
The fields have the following meaning:
The structure of the
The meaning of the fields in the
If scatter/gather is enabled, the fields have the following meaning:
The The For execute I/O requests, the ATA Manager sets the
Bus Inquiry (kATAFnBusInquiry)ATA Manager issues this request to your AIM as the result
of a client's The structure of the
The fields have the following meaning:
I/O Queue Release (kATAFnQRelease)Requests of this type should never be passed through to your AIM. Your AIM should treat this as an unrecognized function code. ATA Command (kATAFnCmd)Requests of this type should never be passed through to your AIM. Your AIM should treat this as an unrecognized function code. Abort Command (kATAFnAbort)Requests of this type should never be passed through to your AIM. Your AIM should treat this as an unrecognized function code. Reset ATA Bus (kATAFnBusReset)ATA Manager issues this request to your AIM as the result
of a client's Register Access (kATAFnRegAccess)ATA Manager issues this request to your AIM as the result
of a client's
The structure of the
The fields have the following meaning:
Drive Identify (kATAFnDriveIdentify)ATA Manager issues this request to your AIM as the result
of a client's
Once it has modified the parameter block in this way, your AIM can simply pass this request through to the execute I/O logic. Execute ATAPI I/O (kATAPIFnExecIO)Requests of this type should never be passed through to your AIM. Your AIM should treat this as an unrecognized function code. ATAPI Command (kATAPIFnCmd)Requests of this type should never be passed through to your AIM. Your AIM should treat this as an unrecognized function code. Get Drive Configuration (kATAFnGetDriveConfig)ATA Manager issues this request to your AIM as the result
of a client's The structure of the
The fields have the following meaning:
Set Drive Configuration (kATAFnSetDriveConfig)ATA Manager issues this request to your AIM as the result
of a client's
The
Kill Current I/O (kATAFnKillIO)The ATA Manager issues this request to your AIM as part
of the process of removing your ATA
bus. You AIM must respond to this request by terminating
any hardware transaction on the ATA bus. This is an
immediate request: your AIM must complete the request before
returning from its action routine
(
|
AIM Support RoutinesThis section describes the AIM support routines exported by the ATA Manager for convenience of AIMs. Your AIM must use the routines described below to signal the ATA Manager that certain events have occurred. ATAFamIODone
Your AIM must call this routine to inform ATA Manager that the AIM action request is complete. ATA Manager executes the following steps:
You must call this routine from the context of your AIM's
action routine
( ATAFamBusEventForAIM
Your AIM must call this routine when it wants to
scheduled its bus event handler
( See AIM Synchronization Model for an in-depth discussion of why this is both necessary and convenient. You may call this routine at any execution level. |
|
|